package com.mall.common.controller;

import static com.mall.common.bean.WebErrors.ERROR_ATTR_NAME;

import java.io.IOException;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Validator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.mall.common.bean.Message;
import com.mall.common.bean.User;
import com.mall.common.bean.WebErrors;
import com.mall.common.exception.NoticeException;
import com.mall.common.exception.ResourceNotFoundException;
import com.mall.common.template.directive.FlashMessageDirective;
import com.mall.common.util.AppContext;
import com.mall.common.util.SpringUtils;

public class BaseController {
	
	@Resource private Validator validator;
	protected static final String ADMIN_ERROR_PAGE = "/admin/error.jhtml";
	protected static final String FRONT_ERROR_PAGE = "/frontError.jhtml";
	protected static final String MEMBER_SUCCESS = "redirect:/member/success.jhtml";
	protected static final String CONSTRAINT_VIOLATIONS = "constraintViolations";
	//submit提交后，关闭当前的tab，并且刷新父页面
	protected static final String CLOSEANRELOAPARENT = "/admin/common/closeAndReloadParent"; 
	protected static final Message errorMessage = Message.error("操作失败", new Object[0]);
	protected static final Message successMessage = Message.success("操作成功", new Object[0]);
	protected Log log = LogFactory.getLog(getClass());

	@SuppressWarnings("rawtypes")
	protected boolean validate(Object obj, final Class<?>... groups) {
		Set set = validator.validate(obj, groups);
		if (set.isEmpty()) {
			return true;
		} else {
			RequestAttributes requestattributes = RequestContextHolder.currentRequestAttributes();
			requestattributes.setAttribute(CONSTRAINT_VIOLATIONS, set, 0);
			return false;
		}
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	protected boolean validate(Class beanType, String propertyName, Object value, final Class<?>... groups) {
		Set set = validator.validateValue(beanType, propertyName, value, groups);
		if (set.isEmpty()) {
			return true;
		} else {
			RequestAttributes requestattributes = RequestContextHolder.currentRequestAttributes();
			requestattributes.setAttribute(CONSTRAINT_VIOLATIONS, set, 0);
			return false;
		}
	}
	
	protected String getMessage(String code, Object aobj[]) {
		return SpringUtils.getMessage(code, aobj);
	}

	protected void redirect(RedirectAttributes redirectattributes, Message message) {
		if (redirectattributes != null && message != null){
			redirectattributes.addFlashAttribute(FlashMessageDirective.FLASH_MESSAGE_ATTRIBUTE_NAME, message);
		}
	}
	
	protected void addActionError(HttpServletRequest request, String message){
		WebErrors errors = (WebErrors)request.getAttribute(ERROR_ATTR_NAME);
		if(errors == null){
			errors = WebErrors.create();
			request.setAttribute(ERROR_ATTR_NAME, errors);
		}
		errors.addErrorString(message);
	}
	
	/**
	 * 发送utf8的请求
	 * @param url
	 * @return
	 * @throws IOException
	 */
    protected String renderHtmlUTF8(String url, HttpServletResponse response) throws IOException{
		response.setContentType("text/html;charset=UTF-8");
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setHeader("Cache-Control", "no-store");  
		response.setDateHeader("Expires", 0);
		response.getWriter().write(url);
		response.getWriter().flush();
		return null;
	}
    
	/**
	 * 清除缓存
	 */
	protected void clearCache(HttpServletResponse response){
		response.setContentType("text/html;charset=UTF-8");
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache"); 
		response.setHeader("Cache-Control", "no-store");  
		response.setDateHeader("Expires", 0);
	}
	
	@ExceptionHandler
	public void exceptionHandler(Exception ex,
			HttpServletResponse response, HttpServletRequest request) throws IOException, ServletException{
		boolean isBackstage = request.getRequestURI().contains("/admin/");
		if(AppContext.isAjax(request)){
			if(ex.getClass() == NoticeException.class){
				this.addActionError(request, ex.getMessage());
			}else{
				log.error("System Error", ex);
				this.addActionError(request, "系统错误!");
			}
			WebErrors errors = (WebErrors)request.getAttribute(ERROR_ATTR_NAME);
			errors.showErrorAjax(response);
		}else{
			if(ex.getClass() == NoticeException.class){
				this.addActionError(request, ex.getMessage());
				request.getRequestDispatcher(isBackstage?ADMIN_ERROR_PAGE : FRONT_ERROR_PAGE).forward(request, response);
			}else if(ex.getClass() == ResourceNotFoundException.class){
				response.sendRedirect("/common/resource_not_found.jhtml");
			}else{
				log.error("System Error", ex);
				response.sendRedirect("/html/error_page_404.html");
			}
		}
	}
	
	/**
	 * 跳转到404页面
	 * @param response
	 * @return
	 * @throws IOException
	 */
	protected String redirectTo404(HttpServletResponse response) throws IOException{
		response.sendRedirect("/html/error_page_404.html");
		return null;
	}
	
	/**
	 * 获得用户
	 * @param request
	 * @return
	 */
	public User getUser() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication == null) {
			return null;
		}
		Object principal = authentication.getPrincipal();
		if (principal == null || !(principal instanceof User)) {
			return null;
		} else {
			return (User) principal;
		}
	}
	
	/**
	 * 获得用户ID
	 * 
	 * @param request
	 * @return
	 */
	public Long getUserId() {
		User user = getUser();
		if (user != null) {
			return user.getId();
		} else {
			return null;
		}
	}
	
	/**
	 * 获取用户名
	 * @return
	 */
	public String getUsername(){
		User user = getUser();
		if (user != null) {
			return user.getUsername();
		} else {
			return null;
		}
	}

}
